Skip to main content

Call an API

Before calling an API, you will need to sign a request and validate a signature. After sending the request and obtaining the response, you need to validate the response signature accordingly. You need to follow this signature rule for all APIs.

note

If a request does not contain sensitive information, encryption is not required.

Sign a Request

Below is the procedure needed to sign a request:

  1. Generate a PrivateKey to sign a request.
  • In development VodaPay will generate the Private and Public key pair and send the Private key to the Merchant.
  • In production the Merchant needs to generate their own Private and Public key pair and send the Public key to VodaPay.
  1. Construct the content to be signed by complying with the following format, this is known as unsignedContent:
<HTTP METHOD>
<HTTP ENDPOINT>
<Client-Id
>.<Request-Time>.<HTTP BODY></HTTP></Request-Time></Client-Id></HTTP
></HTTP>
  • HTTP METHOD: The HTTP method that you need to use when calling VodaPay APIs is POST
  • HTTP ENDPOINT: This will be the endpoint you are sending the request to for example if this is the HTTP URL https://example.com/path/v2/payments/pay then the endpoint will be /v2/payments/pay
  • Client-Id: This is the ClientId used to identify a client and will be provided to the merchant by VodaPay.
  • Request-Time: Specifies the time when a request is sent, as defined by RFC3339.
note

The request time must be accurate to seconds.
E.g 2019-05-28T12:12:12+08:00

  • HTTP BODY: The data of the request body.

Below is an example of how you can generate unsigned content:

const unsignedContent = `${METHOD} ${endPoint}\n${CLIENT_ID}.${
Request - Time
}.${JSON.stringify(body)}`;
  1. Generate a signature using the unsigned content and the private key.
  2. Add the generated signature to the request headers.

1. Generate a Private Key

If you are in the Development stage request for the Private key which is configured with your Sandbox Client and Merchant IDs from the VodaPay team.
If you are on production please generate your your own Private and Public key pair.

2. Construct the content to be signed

An example of how to sign a Request

Let's generate unsigned content using the following properties:

  • Method: POST
  • Endpoint : /v2/authorizations/applyToken
  • Client-Id : 2020122600000000003336
  • Request-Time : 2022-07-29T15:32:09.000+02:00
  • Request body :
{
"grantType": "AUTHORIZATION_CODE",
"authCode": "000000000174MsckxAbW76iB00291783"
}

Result of the unsigned content using the above properties:

POST /v2/authorizations/applyToken
2020122600000000003336.2022-07-29T15:32:09.000+02:00.{"grantType":"AUTHORIZATION_CODE","authCode":"000000000174MsckxAbW76iB00291783"}

3. Generate a signature

Use the base64UrlEncode method that involves the proper algorithm and private key to generate the signature.

Example on how to generate a signature:

const privateKeyObj = crypto.createPrivateKey(privateKeyData, 'utf8');
const signer = crypto.createSign('RSA-SHA256');
signer.write(unsignedContent);
signer.end();
const encodedSignature = signer.sign(privateKeyObj, 'base64');
  • unsignedContent: the content to be signed that is obtained in the previous example.
  • The algorithm to use is RSA256.
  • privateKeyData : The content of the private key value that is obtained in the previous step.

An example of a generated signature using the unsigned content from our previous example:

"ncQZOlrdt8veapdh9oYeXhkHO8Dstq9ULlTE0MUAPPx1UOQB+AXG6J4rSdgsnLrYaBr+dciFX+aDML1HVeywHa9ChP4P4V8MNDCuekADLMjYEG9NhzhHPZ6Se0twTY2FAUJwxqSpodRaphrYrvE/k8cw6pOrOGGN7K34I+ph02H9e6iITPXTBR56PsJVPy0DjqRfKWYqCbao2wm8KnqMYPXeplrvoWUUijvQUcoqqSbtSdyV8JHa/9rL1ZZ4g8XpO126HcdGMq6WTM92KVntMgTkHkKlHjGvLk+WAHdKxvCnTjBYanN3eoluxWqUPnHnRyPMjuWlGLYpeful/i1X2A=="

4. Add generated signature to the header

Assemble the signature algorithm, the key version used for the signature, and the signature (that is generated in the above example) into the Signature header. The following example shows a finished Signature header:

key: Signature; value: algorithm=<algorithm
>, keyVersion=<key-version>, signature=<signature></signature></key-version
></algorithm>

Examaple using the above generated signature:

{
"signature": "algorithm=RSA256, keyVersion=1, signature=ncQZOlrdt8veapdh9oYeXhkHO8Dstq9ULlTE0MUAPPx1UOQB+AXG6J4rSdgsnLrYaBr+dciFX+aDML1HVeywHa9ChP4P4V8MNDCuekADLMjYEG9NhzhHPZ6Se0twTY2FAUJwxqSpodRaphrYrvE/k8cw6pOrOGGN7K34I+ph02H9e6iITPXTBR56PsJVPy0DjqRfKWYqCbao2wm8KnqMYPXeplrvoWUUijvQUcoqqSbtSdyV8JHa/9rL1ZZ4g8XpO126HcdGMq6WTM92KVntMgTkHkKlHjGvLk+WAHdKxvCnTjBYanN3eoluxWqUPnHnRyPMjuWlGLYpeful/i1X2A=="
}

Send a Request

Construct a request by adding the Client-Id, Request-Time, and Signature properties to the request header. The value of the Signature is obtained from the above example. After a request is constructed, you can use common tools, like cURL or Postman to send the request.

POST
https://example.com/v2/authorizations/applyToken
Request Headers

{
"Content-Type": "application/json",
"client-id": "2020122600000000003336",
"request-time": "2022-07-29T15:32:09.000+02:00"
"signature": "algorithm=RSA256, keyVersion=1, signature=ncQZOlrdt8veapdh9oYeXhkHO8Dstq9ULlTE0MUAPPx1UOQB+AXG6J4rSdgsnLrYaBr+dciFX+aDML1HVeywHa9ChP4P4V8MNDCuekADLMjYEG9NhzhHPZ6Se0twTY2FAUJwxqSpodRaphrYrvE/k8cw6pOrOGGN7K34I+ph02H9e6iITPXTBR56PsJVPy0DjqRfKWYqCbao2wm8KnqMYPXeplrvoWUUijvQUcoqqSbtSdyV8JHa/9rL1ZZ4g8XpO126HcdGMq6WTM92KVntMgTkHkKlHjGvLk+WAHdKxvCnTjBYanN3eoluxWqUPnHnRyPMjuWlGLYpeful/i1X2A=="
}

Request Body

{
"grantType":"AUTHORIZATION_CODE",
"authCode":"000000000174MsckxAbW76iB00291783"
}

Handle a Response

After you receive a response, you need to validate the signature of the response.

A response consists of response headers and response body. For example:

POST
https://example.com/api/payment-notify
Response Headers

{
"client-id": "2020122600000000003336",
"response-time": "2022-07-29T15:32:09.000+02:00"
"signature": "algorithm=RSA256, keyVersion=1, signature=ncQZOlrdt8veapdh9oYeXhkHO8Dstq9ULlTE0MUAPPx1UOQB+AXG6J4rSdgsnLrYaBr+dciFX+aDML1HVeywHa9ChP4P4V8MNDCuekADLMjYEG9NhzhHPZ6Se0twTY2FAUJwxqSpodRaphrYrvE/k8cw6pOrOGGN7K34I+ph02H9e6iITPXTBR56PsJVPy0DjqRfKWYqCbao2wm8KnqMYPXeplrvoWUUijvQUcoqqSbtSdyV8JHa/9rL1ZZ4g8XpO126HcdGMq6WTM92KVntMgTkHkKlHjGvLk+WAHdKxvCnTjBYanN3eoluxWqUPnHnRyPMjuWlGLYpeful/i1X2A==",
"Trace-Id": "0ba604b41558615600801371953814.0"
}

Response Body

{
"paymentId": "201911271907410100070000009999",
"paymentRequestId": "2019112719074101000700000088881",
"paymentAmount": {
"currency": "USD",
"value": "10000"
},
"paymentTime": "2019-11-27T12:02:01+08:30",
"paymentResult": {
"resultCode":"SUCCESS",
"resultStatus":"S",
"resultMessage":"success"
}
}

Validate signature

Use the sha256withrsa_verify method to validate the signature of a response.

Example on how to validate a signature:

const publicKeyObj = crypto.createPublicKey(publicKeyData, 'utf8');
const verifyer = crypto.createVerify('RSA-SHA256');
verifyer.write(unsignedContent);
verifyer.end();
const verifies = verifyer.verify(publicKeyObj, signature, 'base64');
  • signature: This is the signature which is found on the response headers.
  • publicKeyData: This is the server Public Key or the platform public key. In this case this will be VodaPay public key. Please do not use your own public key to verify the signature.
  • unsignedContent: The content to be validated. Construct the content using the similar format like we did when generating the unsigned content when sending a request.
  • verifies: Verifies will return true if the signature is successfully validated and return false if the signature is not valid.
note

When generating the usigned content to verify the signature. Use response-time instead of request-time and response body instead of request body.

Let's generate unsigned content to verify a signature using the following properties:

  • Method: POST
  • Endpoint : /api/payment-notify
  • Client-Id : 2020122600000000003336
  • Response-Time : 2022-07-29T15:32:09.000+02:00
  • Response body :
{
"paymentId": "201911271907410100070000009999",
"paymentRequestId": "2019112719074101000700000088881",
"paymentAmount": {
"currency": "USD",
"value": "10000"
},
"paymentTime": "2019-11-27T12:02:01+08:30",
"paymentResult": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}

Below is the unsigned content that we generated using the above properties:

POST /api/payment-notify
2020122600000000003336.2022-07-29T15:32:09.000+02:00.{"result":{"resultCode":"SUCCESS","resultStatus":"S","resultMessage":"success"},"accessToken":"000000000220220913WR93nYXanS02uL00054453","accessTokenExpiryTime":"2032-09-10T14:10:58+02:00","refreshToken":"000000000320220913Lf4uZ5JvYa02le00056216","refreshTokenExpiryTime":"2032-09-10T14:10:58+02:00","customerId":"216610000000672732025"}